package ypmits.bitmap {
	import ypmits.bitmap.input.BitmapModInput;
	import ypmits.bitmap.vo.ParticleDataVO;
	import ypmits.utils.SimpleMath;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.GradientType;
	import flash.display.PixelSnapping;
	import flash.display.Shape;
	import flash.display.SpreadMethod;
	import flash.display.Sprite;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 * @author Dave Lenz
	 */
	public class BitmapModifierTool {
		/**
		 * @author Merten Snijders
		 */
		public static function getShapeFromBitmap( _i : BitmapModInput ) : BitmapData {
			if (!_i.alpha.transparent) throw new Error( "BitmapData alpha requires to have transparency" );
			_i.source.copyPixels( _i.source, _i.destinationRectangle, _i.sourcePoint, _i.alpha, _i.alphaPoint, false );
			return _i.source;
		}

		
		/**
		 * use Punch to drill holes in excisting Bitmaps (Merten Snijders)
		 */
		public static function Punch( bitmap : Bitmap, drillRect : Rectangle ) : Bitmap {
			bitmap.bitmapData.fillRect( drillRect, 0 );
			return bitmap;
		}

		
		/**
		 * @author Merten Snijders
		 */
		public static function getRectFromBitmap( _i : BitmapModInput ) : BitmapData {
			var bmp : BitmapData = new BitmapData( _i.destinationRectangle.width, _i.destinationRectangle.height, false, 0x000000 );
			bmp.copyPixels( _i.source, _i.destinationRectangle, _i.sourcePoint );
			return bmp;
		}

		
		/**
		 * @author Merten Snijders
		 */
		public static function resample( _bmp : BitmapData, _perc : Number, _maintainBitmap : Boolean = false ) : BitmapData {
			var m : Matrix = new Matrix( );
			m.scale( _perc, _perc );
			
			var resampled : BitmapData = new BitmapData( _bmp.width * _perc, _bmp.height * _perc, false, 0x000000 );
			resampled.draw( _bmp, m, null, null, null, true );
			
			if (!_maintainBitmap) _bmp.dispose( );

			return resampled;
		}

		
		public static function border( _bmp : BitmapData, _borderThickness : Number, _borderColor : Number = 0xEEEEEE ) : BitmapData {
			_bmp.fillRect( new Rectangle( 0, 0, _bmp.width, _borderThickness ), _borderColor );
			_bmp.fillRect( new Rectangle( 0, 0, _borderThickness, _bmp.height ), _borderColor );
			_bmp.fillRect( new Rectangle( 0, _bmp.height - _borderThickness, _bmp.width, _borderThickness ), _borderColor );
			_bmp.fillRect( new Rectangle( _bmp.width - _borderThickness, 0, _borderThickness, _bmp.height ), _borderColor );
			return _bmp;	
		}

		
		/**
		 * @author Merten Snijders
		 */
		public static function flipH( _b : BitmapData ) : BitmapData {

			var m : Matrix = new Matrix( );
			m.scale( -1, 1 );
			m.translate( _b.width, 0 );
			
			var bmp : BitmapData = new BitmapData( _b.width, _b.height, false, 0x000000 );
			bmp.draw( _b, m, null, null, null, true );
			
			return bmp;
		}

		
		/**
		 * @author Merten Snijders
		 */
		public static function flipV() : void {
		}

		
		/**
		 * BitmapTool.mirror is used to mirror a DisplayObject
		 * </br>
		 * @author davelenz
		 * @version 1
		 * </br>
		 * Usage: <code>BitmapTool.mirror</code> returns a clone of the bitmap you put in.
		 * </br>
		 * @param bitmap The bitmap to mirror
		 * @param startalpha The alpha-value on top from 0 to 1. Default is 1
		 * @param endalpha The alpha-value below from 0 to 1. Default = 0
		 * @param percentageofbitmap The percentage-height of the bitmap to use for the fade
		 * @param yOffset The offset of the mirrored bitmap
		 */
		public static function mirror( obj : DisplayObject, startalpha : Number = 1, endalpha : Number = 0, percofbitmap : Number = 1, yOffset : Number = 0 ) : Sprite {
			var holder : Sprite = new Sprite( );

			var m : Matrix = new Matrix( );
			m.translate( 0, -obj.height );
			m.scale( 1, -1 );
			var bitmapdata : BitmapData = new BitmapData( obj.width, obj.height, true, 0xFF9900 );

			var newbitmap : Bitmap = new Bitmap( bitmapdata );
			bitmapdata.draw( obj, m );
			newbitmap.y = yOffset;
			newbitmap.smoothing = true;
			holder.addChild( newbitmap );

			var gradientmasker : Shape = getMirrorGradient( newbitmap, startalpha, endalpha, percofbitmap );
			gradientmasker.y = yOffset;
			holder.addChild( gradientmasker );

			newbitmap.cacheAsBitmap = true;
			gradientmasker.cacheAsBitmap = true;
			newbitmap.mask = gradientmasker;

			return holder;
		}

		
		private static function getMirrorGradient( bitmap : Bitmap, startalpha : Number = 1, endalpha : Number = 0, percofbitmap : Number = 1 ) : Shape {
			var m : Matrix = new Matrix( );
			m.createGradientBox( bitmap.width, percofbitmap * bitmap.height, SimpleMath.degreesToRadians( 90 ) );

			var gradient : Shape = new Shape( );
			gradient.graphics.clear( );
			gradient.graphics.beginGradientFill( GradientType.LINEAR, [ 0xFF9900, 0xFF9900 ], [ startalpha, endalpha ], [ 0, 255 ], m, SpreadMethod.PAD );  
			gradient.graphics.drawRect( 0, 0, bitmap.width, percofbitmap * bitmap.height );
			gradient.graphics.endFill( );

			return gradient;
		}

		
		public static function convertToBitmap( obj : DisplayObject, w : Number = 100, h : Number = 100, smoothing : Boolean = false, translationsMatrix : Matrix = null ) : Bitmap {
			var bitmapdata : BitmapData = new BitmapData( w, h, true, 0xFF9900 );

			var newbitmap : Bitmap = new Bitmap( bitmapdata );
			bitmapdata.draw( obj, translationsMatrix );
			newbitmap.smoothing = smoothing;
			
			return newbitmap;
		}

		
		public static function convertSpecialSize( obj : DisplayObject, smoothing : Boolean = false, w : Number = 100, h : Number = 100 ) : Bitmap {
			var m : Matrix = new Matrix( );
			var bitmapdata : BitmapData = new BitmapData( w, h, true, 0xFF9900 );
			
			var newbitmap : Bitmap = new Bitmap( bitmapdata );
			bitmapdata.draw( obj, m );
			newbitmap.smoothing = smoothing;
			
			return newbitmap;
		}

		
		/**
		 * @return an Array which contains the image-particles as type 'ParticleData'
		 */
		public static function makeBitmapParticles( bitmapdata : BitmapData, width : Number, height : Number, alpha : Boolean = false ) : Array {
			var particles : Array = [];
			
			var columns : Number = bitmapdata.width; // / width;
			var rows : Number = bitmapdata.height; // / height;
			trace("columns:"+columns);
			trace("rows:"+rows);
			
			var i : int;
			var bmd : BitmapData;
			for ( i = 0; i < rows; i++) {
				for (var j : int = 0; j < columns; j++) {
					bmd = new BitmapData( width, height, alpha, Math.random( ) * 0xFFFFFF );
					bmd.copyPixels( bitmapdata, new Rectangle( j * bmd.width, i * bmd.height, width, height ), new Point( 0, 0 ) );

					particles.push( new ParticleDataVO( j * bmd.width, i * bmd.height, new Bitmap( bmd, PixelSnapping.AUTO, false ) ) );
				}
			}
			return particles;
		}

		
		public static function mergeBitmap( data_a : BitmapData, data_b : BitmapData ) : BitmapData 
		{
			var mergeddata : BitmapData = data_a;
			mergeddata.draw( data_b );
			return mergeddata;
		}		
	}
}
